package com.app.common;

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.text.SimpleDateFormat;
import java.util.Date;

public class CheckIdCard {
//    // 计算身份证校验码，根据国家标准GB 11643-1999
//    public boolean idCardVerifyNumber(String idCardBase) {
//        if (idCardBase.length() != 17) {
//            return false;
//        }
//        //加权因子
//        int[] factor = {7, 9, 10, 5, 8, 4, 2, 1, 6, 3, 7, 9, 10, 5, 8, 4, 2};
//        //校验码对应值
//        char[] verifyNumberList = {'1', '0', 'X', '9', '8', '7', '6', '5', '4', '3', '2'};
//        int checksum = 0;
//        for (int i = 0; i < idCardBase.length(); i++) {
//            checksum += Integer.valueOf(idCardBase.substring(i, 1)) * factor[i];
//        }
//        int mod = checksum % 11;
//        verifyNumber = verifyNumberList[mod];
//        return verifyNumber;
//    }
//
//    // 18位身份证校验码有效性检查
//    public boolean idCardCheck(String idCard) {
//        if (idCard.length() != 18) {
//            return false;
//        }
//        String idCardBase = idCard.substring(0, 17);
//        if (idCardVerifyNumber(idCardBase) != strtoupper(substr($idcard, 17, 1))) {
//            return false;
//        } else {
//            return true;
//        }
//    }


    /**
     * @author PDH
     * 华师大中国大学Mooc Java核心技术编程作业，部分代码参考：https://blog.csdn.net/qq_38971856/article/details/94415178
     */
/*验证身份证号码是否正确(带校验算法)
题目内容：
输入一个字符串，请判断是否满足身份证基本要求，并返回具体的生日yyyy-mm-dd。
如果输入数据有误，请输出0000-00-00。
基本要求是：a)必须是18位；b) 前面位数必须是数字，最后一位可以是数字或小写字母；c) 日期是存在的；d)最后一位校验码检查。
校验码规则如下：
1、将前面的身份证号码17位数分别乘以不同的系数。从第一位到第十七位的系数分别为：7－9－10－5－8－4－2－1－6－3－7－9－10－5－8－4－2。
2、将这17位数字和系数相乘的结果相加。
3、用加出来和除以11，看余数是多少？
4、余数只可能有0－1－2－3－4－5－6－7－8－9－10这11个数字。其分别对应的最后一位身份证的号码为1－0－X－9－8－7－6－5－4－3－2。
5、通过上面得知如果余数是3，就会在身份证的第18位数字上出现的是9。如果对应的数字是10，身份证的最后一位号码就是罗马数字x。
输入格式:
一个身份证号，18位
输出格式：
yyyy-mm-dd
输入样例：
53010219200508011x
输出样例：
1920-05-08
时间限制：500ms内存限制：32000kb
*/

    public class P9_IDChecker {


//        {
//            String id;
//            int checkResult = 0;
//
//            //创建一个IDChecker类
//            IDChecker2 idc = new IDChecker2();
//            do {
//                //输入身份证号
//                id = idc.enterID();
//                //验证身份证号
//                checkResult = idc.checkID(id);
//                switch (checkResult) {
//                    case -1, -2, -3, -4:
//                        System.out.println("0000-00-00");
//                        System.out.println("请重新输入！");
//                        break;
//                    case 1:
//                        System.out.println("身份证号符合当前所有校验规则！");
//                        System.out.println("出生日期："+id.substring(6, 10)+"-"+id.substring(10, 12)+"-"+id.substring(12, 14));
//                        break;
//                    default:
//                        break;
//                }
//            }
//            while (checkResult!=1);
//
//        }

    }

    class IDChecker2 {
        private String id;

        public IDChecker2() {

        }

        public String enterID() {
            System.out.println("请输入身份证号：");
            BufferedReader input = new BufferedReader(new InputStreamReader(System.in));
            try {
                id = input.readLine();
            } catch (IOException e) {
                // TODO Auto-generated catch block
                e.printStackTrace();
            }
            return id;
        }


        public int checkID(String id) {
            //a)必须是18位
            int lc = lengthCheck(id);
            if (lc < 0) return lc;

            //b) 前面位数必须是数字，最后一位可以是数字或小写字母；
            int dic = digitCheck(id);
            if (dic < 0) return dic;

            //c) 日期是存在的。
            int dac = dateCheck(id);
            if (dac < 0) return dac;

            //d)最后一位校验码检查。
            int ldc = lastDigitCheck(id);
            if (ldc < 0) return ldc;

            //所有校验通过后，返回1
            return 1;

        }

        public int lengthCheck(String id) {
            //a)必须是18位
            if (id.length() != 18) {
                System.out.println("输入错误：位数不是18位！");
                return -1;
            }
            return 0;
        }

        public int digitCheck(String id) {
            //b) 前面位数必须是数字，最后一位可以是数字或小写字母；
            int i, n = 0;
            for (i = 0; i < 17; i++) {
                if (id.charAt(i) >= '0' && id.charAt(i) <= '9') {
                    n++;
                } else
                    break;
            }

            if (n <= 16 || !((id.charAt(17) >= '0' && id.charAt(17) <= '9') || (id.charAt(17) >= 'a' && id.charAt(17) <= 'z'))) {
                System.out.println("输入错误：前面位数必须是数字，最后一位可以是数字或小写字母！");
                return -2;
            }
            return 0;
        }

        public int dateCheck(String id) {
            //c) 日期是存在的。
            int year, month, day;
            year = Integer.valueOf(id.substring(6, 10));
            month = Integer.valueOf(id.substring(10, 12));
            day = Integer.valueOf(id.substring(12, 14));

            String strDate = id.substring(6, 14);
            // 准备第一个模板，从字符串中提取出日期数字
            String pat1 = "yyyyMMdd";
            // 准备第二个模板，将提取后的日期数字变为指定的格式
            String pat2 = "yyyy-MM-dd";
            SimpleDateFormat sdf1 = new SimpleDateFormat(pat1);        // 实例化模板对象
            SimpleDateFormat sdf2 = new SimpleDateFormat(pat2);        // 实例化模板对象
            Date d = null;
            try {
                d = sdf1.parse(strDate);   // 将给定的字符串中的日期提取出来
            } catch (Exception e) {            // 如果提供的字符串格式有错误，则进行异常处理
                e.printStackTrace();       // 打印异常信息
            }
            String r = sdf1.format(d);
            if (!r.equals(strDate)) {
                System.out.println("输入错误：无效的出生日期！");
                return -3;
            }
//        else
//            System.out.println(sdf2.format(d)) ;    // 将日期变为新的格式
//
            return 0;
        }

        public int lastDigitCheck(String id) {
            //d)最后一位校验码检查。
            /*
             * 校验码规则如下：
             * 1、将前面的身份证号码17位数分别乘以不同的系数。从第一位到第十七位的系数分别为：7－9－10－5－8－4－2－1－6－3－7－9－10－5－8－4－2。
             * 2、将这17位数字和系数相乘的结果相加。
             * 3、用加出来和除以11，看余数是多少？
             * 4、余数只可能有0－1－2－3－4－5－6－7－8－9－10这11个数字。其分别对应的最后一位身份证的号码为1－0－X－9－8－7－6－5－4－3－2。
             * 5、通过上面得知如果余数是3，就会在身份证的第18位数字上出现的是9。如果对应的数字是10，身份证的最后一位号码就是罗马数字x。
             */

            //1.系数数组定义
            int[] factors = {7, 9, 10, 5, 8, 4, 2, 1, 6, 3, 7, 9, 10, 5, 8, 4, 2};
            //2.求和
            int sum = 0;
            for (int i = 0; i < 17; i++) {
                sum += (id.charAt(i) - '0') * factors[i];
            }
            //3.取余
            int remainder = sum % 11;
            //4.余数映射数组定义
            char[] mappedDigits = {'1', '0', 'X', '9', '8', '7', '6', '5', '4', '3', '2'};
            //5.生成最后一位（校验位）
            char lastDigit = mappedDigits[remainder];
//        System.out.println("校验位："+lastDigit);
            //判断输入的最后一位是否符合校验规则
            if (id.charAt(17) != lastDigit) {
                System.out.println("输入错误：最后一位不符合校验规则");
                return -4;
            }
            return 0;
        }
    }

}
